"""
消息推送相关的请求/响应数据模型
"""
from datetime import datetime
from typing import Optional, List, Dict, Any

from pydantic import BaseModel, Field, validator, ConfigDict

from app.models.notification_models import (
	NotificationType, NotificationPriority, NotificationStatus
)


class NotificationCreateRequest(BaseModel):
    """
    创建消息请求模型
    """
    user_ids: List[int] = Field(..., description="接收用户ID列表", min_items=1, max_items=1000)
    type: NotificationType = Field(..., description="消息类型")
    priority: NotificationPriority = Field(NotificationPriority.NORMAL, description="优先级")
    title: str = Field(..., description="消息标题", max_length=128)
    content: Optional[str] = Field(None, description="消息内容", max_length=2000)
    data_json: Optional[Dict[str, Any]] = Field(None, description="扩展数据")
    expire_time: Optional[datetime] = Field(None, description="过期时间")

    @validator('user_ids')
    def validate_user_ids(cls, v):
        """验证用户ID列表"""
        if not v:
            raise ValueError("用户ID列表不能为空")
        # 去重
        unique_ids = list(set(v))
        if len(unique_ids) != len(v):
            v = unique_ids
        # 验证每个ID都是正数
        for user_id in v:
            if user_id <= 0:
                raise ValueError("用户ID必须大于0")
        return v

    @validator('title')
    def validate_title(cls, v):
        """验证消息标题"""
        if not v or not v.strip():
            raise ValueError("消息标题不能为空")
        return v.strip()

    @validator('content')
    def validate_content(cls, v):
        """验证消息内容"""
        if v and len(v.strip()) == 0:
            return None
        return v.strip() if v else v

    @validator('expire_time')
    def validate_expire_time(cls, v):
        """验证过期时间"""
        if v and v <= datetime.now():
            raise ValueError("过期时间必须晚于当前时间")
        return v


class NotificationCreateResponse(BaseModel):
    """
    创建消息响应模型
    """
    success_count: int = Field(..., description="成功创建数量")
    failed_count: int = Field(..., description="失败创建数量")
    notification_ids: List[int] = Field(default_factory=list, description="创建成功的消息ID列表")
    failed_user_ids: List[int] = Field(default_factory=list, description="创建失败的用户ID列表")

    @property
    def total_count(self) -> int:
        """总创建数量"""
        return self.success_count + self.failed_count

    @property
    def success_rate(self) -> float:
        """成功率"""
        if self.total_count == 0:
            return 0
        return round((self.success_count / self.total_count) * 100, 2)


class NotificationResponse(BaseModel):
    """
    消息详情响应模型
    """
    id: int = Field(..., description="消息ID")
    type: NotificationType = Field(..., description="消息类型")
    priority: NotificationPriority = Field(..., description="优先级")
    title: str = Field(..., description="消息标题")
    content: Optional[str] = Field(None, description="消息内容")
    data_json: Optional[Dict[str, Any]] = Field(None, description="扩展数据")
    read_flag: NotificationStatus = Field(..., description="读取状态")
    expire_time: Optional[datetime] = Field(None, description="过期时间")
    gmt_create: datetime = Field(..., description="创建时间")

    @property
    def is_read(self) -> bool:
        """是否已读"""
        return self.read_flag == NotificationStatus.READ

    @property
    def is_expired(self) -> bool:
        """是否已过期"""
        if not self.expire_time:
            return False
        return datetime.now() > self.expire_time

    @property
    def is_urgent(self) -> bool:
        """是否紧急消息"""
        return self.priority == NotificationPriority.URGENT

    @property
    def age_hours(self) -> int:
        """消息年龄（小时）"""
        return int((datetime.now() - self.gmt_create).total_seconds() / 3600)

    model_config = ConfigDict(from_attributes=True)


class NotificationListRequest(BaseModel):
    """
    消息列表查询请求模型
    """
    page: int = Field(1, description="页码", ge=1)
    page_size: int = Field(20, description="每页大小", ge=1, le=100)
    type: Optional[NotificationType] = Field(None, description="消息类型筛选")
    priority: Optional[NotificationPriority] = Field(None, description="优先级筛选")
    read_flag: Optional[NotificationStatus] = Field(None, description="读取状态筛选")
    start_time: Optional[datetime] = Field(None, description="开始时间")
    end_time: Optional[datetime] = Field(None, description="结束时间")
    keyword: Optional[str] = Field(None, description="标题或内容关键词", max_length=50)
    include_expired: bool = Field(True, description="是否包含已过期消息")
    only_unread: bool = Field(False, description="是否只显示未读消息")

    @validator('keyword')
    def validate_keyword(cls, v):
        """验证关键词"""
        if v and not v.strip():
            raise ValueError("关键词不能为空字符串")
        return v.strip() if v else v

    @validator('end_time')
    def validate_time_range(cls, v, values):
        """验证时间范围"""
        if v and 'start_time' in values and values['start_time']:
            if v <= values['start_time']:
                raise ValueError("结束时间必须晚于开始时间")
        return v


class NotificationListResponse(BaseModel):
    """
    消息列表响应模型
    """
    total: int = Field(..., description="总数量")
    items: List[NotificationResponse] = Field(default_factory=list, description="消息列表")
    page: int = Field(..., description="当前页码")
    page_size: int = Field(..., description="每页大小")
    total_pages: int = Field(..., description="总页数")
    unread_count: int = Field(0, description="未读消息数")

    @property
    def has_next(self) -> bool:
        """是否有下一页"""
        return self.page < self.total_pages

    @property
    def has_prev(self) -> bool:
        """是否有上一页"""
        return self.page > 1


class NotificationMarkReadRequest(BaseModel):
    """
    标记消息已读请求模型
    """
    notification_ids: List[int] = Field(..., description="消息ID列表", min_items=1, max_items=100)

    @validator('notification_ids')
    def validate_notification_ids(cls, v):
        """验证消息ID列表"""
        if not v:
            raise ValueError("消息ID列表不能为空")
        # 去重
        unique_ids = list(set(v))
        if len(unique_ids) != len(v):
            v = unique_ids
        # 验证每个ID都是正数
        for notification_id in v:
            if notification_id <= 0:
                raise ValueError("消息ID必须大于0")
        return v


class NotificationMarkReadResponse(BaseModel):
    """
    标记消息已读响应模型
    """
    success_count: int = Field(..., description="成功标记数量")
    failed_count: int = Field(..., description="失败标记数量")
    failed_ids: List[int] = Field(default_factory=list, description="标记失败的消息ID列表")

    @property
    def total_count(self) -> int:
        """总标记数量"""
        return self.success_count + self.failed_count


class NotificationSummaryResponse(BaseModel):
    """
    消息摘要响应模型
    """
    total_count: int = Field(0, description="总消息数")
    unread_count: int = Field(0, description="未读消息数")
    urgent_count: int = Field(0, description="紧急消息数")
    expired_count: int = Field(0, description="已过期消息数")

    # 按类型统计
    system_count: int = Field(0, description="系统消息数")
    alarm_count: int = Field(0, description="告警消息数")
    device_count: int = Field(0, description="设备消息数")
    work_order_count: int = Field(0, description="工单消息数")
    user_count: int = Field(0, description="用户消息数")
    maintenance_count: int = Field(0, description="维护消息数")

    @property
    def read_count(self) -> int:
        """已读消息数"""
        return self.total_count - self.unread_count

    @property
    def read_rate(self) -> float:
        """已读率"""
        if self.total_count == 0:
            return 0.0
        return round((self.read_count / self.total_count) * 100, 2)


class NotificationDeleteRequest(BaseModel):
    """
    删除消息请求模型
    """
    notification_ids: List[int] = Field(..., description="消息ID列表", min_items=1, max_items=100)

    @validator('notification_ids')
    def validate_notification_ids(cls, v):
        """验证消息ID列表"""
        if not v:
            raise ValueError("消息ID列表不能为空")
        # 去重
        unique_ids = list(set(v))
        if len(unique_ids) != len(v):
            v = unique_ids
        # 验证每个ID都是正数
        for notification_id in v:
            if notification_id <= 0:
                raise ValueError("消息ID必须大于0")
        return v


class NotificationDeleteResponse(BaseModel):
    """
    删除消息响应模型
    """
    success_count: int = Field(..., description="成功删除数量")
    failed_count: int = Field(..., description="失败删除数量")
    failed_ids: List[int] = Field(default_factory=list, description="删除失败的消息ID列表")

    @property
    def total_count(self) -> int:
        """总删除数量"""
        return self.success_count + self.failed_count


class NotificationTemplateRequest(BaseModel):
    """
    使用模板创建消息请求模型
    """
    template_key: str = Field(..., description="模板键名", max_length=50)
    user_ids: List[int] = Field(..., description="接收用户ID列表", min_items=1, max_items=1000)
    variables: Dict[str, Any] = Field(..., description="模板变量值")
    data_json: Optional[Dict[str, Any]] = Field(None, description="扩展数据")
    expire_time: Optional[datetime] = Field(None, description="过期时间")

    @validator('template_key')
    def validate_template_key(cls, v):
        """验证模板键名"""
        if not v or not v.strip():
            raise ValueError("模板键名不能为空")
        return v.strip()

    @validator('user_ids')
    def validate_user_ids(cls, v):
        """验证用户ID列表"""
        if not v:
            raise ValueError("用户ID列表不能为空")
        # 去重
        unique_ids = list(set(v))
        if len(unique_ids) != len(v):
            v = unique_ids
        return v

    @validator('variables')
    def validate_variables(cls, v):
        """验证模板变量"""
        if not v:
            raise ValueError("模板变量不能为空")
        return v


class NotificationBroadcastRequest(BaseModel):
    """
    广播消息请求模型（发送给所有用户）
    """
    type: NotificationType = Field(..., description="消息类型")
    priority: NotificationPriority = Field(NotificationPriority.NORMAL, description="优先级")
    title: str = Field(..., description="消息标题", max_length=128)
    content: Optional[str] = Field(None, description="消息内容", max_length=2000)
    data_json: Optional[Dict[str, Any]] = Field(None, description="扩展数据")
    expire_time: Optional[datetime] = Field(None, description="过期时间")
    role_filter: Optional[List[str]] = Field(None, description="角色筛选，只发送给指定角色的用户")

    @validator('title')
    def validate_title(cls, v):
        """验证消息标题"""
        if not v or not v.strip():
            raise ValueError("消息标题不能为空")
        return v.strip()

    @validator('role_filter')
    def validate_role_filter(cls, v):
        """验证角色筛选"""
        if v:
            valid_roles = ['admin', 'user', 'operator']
            for role in v:
                if role not in valid_roles:
                    raise ValueError(f"无效的角色: {role}，有效角色: {valid_roles}")
        return v


class NotificationSSEData(BaseModel):
    """
    SSE消息数据模型
    """
    id: int = Field(..., description="消息ID")
    type: NotificationType = Field(..., description="消息类型")
    priority: NotificationPriority = Field(..., description="优先级")
    title: str = Field(..., description="消息标题")
    content: Optional[str] = Field(None, description="消息内容")
    data_json: Optional[Dict[str, Any]] = Field(None, description="扩展数据")
    timestamp: datetime = Field(..., description="时间戳")

    @property
    def is_urgent(self) -> bool:
        """是否紧急消息"""
        return self.priority == NotificationPriority.URGENT


class NotificationStatisticsRequest(BaseModel):
    """
    消息统计请求模型
    """
    start_time: Optional[datetime] = Field(None, description="开始时间")
    end_time: Optional[datetime] = Field(None, description="结束时间")
    user_id: Optional[int] = Field(None, description="指定用户ID（管理员查看）")
    group_by: str = Field("type", description="分组方式：type-按类型，date-按日期，priority-按优先级")

    @validator('group_by')
    def validate_group_by(cls, v):
        """验证分组方式"""
        if v not in ["type", "date", "priority"]:
            raise ValueError("分组方式只能是 type、date 或 priority")
        return v

    @validator('end_time')
    def validate_time_range(cls, v, values):
        """验证时间范围"""
        if v and 'start_time' in values and values['start_time']:
            if v <= values['start_time']:
                raise ValueError("结束时间必须晚于开始时间")
        return v


class NotificationStatisticsResponse(BaseModel):
    """
    消息统计响应模型
    """
    total_count: int = Field(..., description="统计期间总消息数")
    read_count: int = Field(..., description="已读消息数")
    unread_count: int = Field(..., description="未读消息数")
    urgent_count: int = Field(..., description="紧急消息数")
    expired_count: int = Field(..., description="已过期消息数")
    groups: List[Dict[str, Any]] = Field(default_factory=list, description="分组统计数据")

    @property
    def read_rate(self) -> float:
        """已读率"""
        if self.total_count == 0:
            return 0.0
        return round((self.read_count / self.total_count) * 100, 2)
